#!/usr/bin/env python

__author__ = 'Pranav Prakash < x@pranavprakash.in>'

#	This is a demo application about using the Channel API in 
#	Google App Engine. This application does chat and some real
#	actions between a set of users on a room.
#
#	Copyright (C) 2010-2011  Pranav Prakash
#
#	This program is free software: you can redistribute it and/or modify
#	it under the terms of the GNU General Public License as published by
#	the Free Software Foundation, either version 3 of the License, or
#	(at your option) any later version.
#
#	This program is distributed in the hope that it will be useful,
#	but WITHOUT ANY WARRANTY; without even the implied warranty of
#	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#	GNU General Public License for more details.
#   You should have received a copy of the GNU General Public License
#   along with this program.  If not, see <http://www.gnu.org/licenses/>.


import md5
import logging
import time, random

from google.appengine.api import channel

from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext.webapp import template

from django.utils import simplejson

#	The maximum number of participants in the event
#	Keep it -1 for unlimited access

MAX_PARTICIPANTS = 5

class Game(db.Model):
	user    = db.StringListProperty()
	created = db.DateTimeProperty(auto_now_add = True)
	updated = db.DateTimeProperty(auto_now = True)
	chat = db.TextProperty()

class MainPage(webapp.RequestHandler):
	def get(self):
		userid  = self.request.params.get('userid')
		gamekey = self.request.params.get('gamekey')
		logging.info('UserID: %s, GameKey: %s' %(userid, gamekey))
		if userid is None:
			self.response.out.write(template.render('index.html', {
						'gamekey': gamekey}))
			return
		game = None
		if gamekey is None:
			#	No game has been specified. Create a new room and make this
			#	player the first player/attendee
			unique_seed = str(time.time()) + str(random.randint(100,800))
			gamekey = md5.md5(unique_seed).hexdigest()
			game = Game(key_name = gamekey,
						 user = [userid])
			game.put()
		else:
			#	Game exists, find it
			game = Game.get_by_key_name(gamekey)
			if len(game.user) <= MAX_PARTICIPANTS :
				if userid not in game.user:
					game.user.append(userid)
					game.put()
		token = channel.create_channel(userid + gamekey)
		template_values = {'token' : token,
							'userid' : userid,
							'gamekey' : gamekey}
		self.response.out.write(template.render('index.html', template_values))

class GameUpdater():
	game = None
	delta_chat = ''
	gameupdate = {}

	def __init__(self, game):
		self.game = game
	
	def get_game_message(self):
		update = self.gameupdate
		return simplejson.dumps(update)
	
	def send_update(self):
		message = self.get_game_message()
		logging.info('Sending Update. Message: %s' %message)
		for userid in self.game.user:
			logging.info(userid + self.game.key().id_or_name())
			channel.send_message( userid + self.game.key().id_or_name(), message)
		
	def update_chat(self, message):
		"Updates the chat message"
		delta_message = message
		chat = self.game.chat
		if not chat: chat = ''
		chat += '<br />' + delta_message
		self.game.chat = chat
		self.gameupdate.update({'delta_chat' : delta_message})
		self.game.put()
		self.send_update()
	
	def new_entry(self):
		"Announces everyone of a new guy in the room"
		self.gameupdate.update({'new_entry' : 'true',
				 		'name' : self.game.user[-1]})
		self.send_update()



class GameFromRequest():
	game = None
	
	def __init__(self, request):
		userid  = request.params.get('userid')
		gamekey = request.params.get('gamekey')
		logging.info('Userid: %s, GameKey: %s' %(userid, gamekey))
		if userid and gamekey:
			self.game = Game.get_by_key_name(gamekey)
	
	def get_game(self):
		return self.game

class OpenedPage(webapp.RequestHandler):
	""" This is the class that handles as soon a client is ready to make
		connection
	"""
	def post(self):
		game = GameFromRequest(self.request).get_game()
		GameUpdater(game).send_update()
		#GameUpdater(game).new_entry()

class Chat(webapp.RequestHandler):
	""" Handles when players chat between each other
	"""
	def post(self):
		game = GameFromRequest(self.request).get_game()
		message = self.request.params.get('m')	
		if game and message:
			GameUpdater(game).update_chat(message)

application = webapp.WSGIApplication(
                            [('/', MainPage),
							 ('/opened', OpenedPage),
							 ('/chat', Chat)],
                            debug=True)

def main():
	run_wsgi_app(application)

if __name__ == "__main__":
	main()
